<?php
declare (strict_types = 1);

namespace betka\makecmd;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\console\input\Option;

class ToObj extends Command
{
    /**
     * 应用基础目录
     * @var string
     */
    protected $basePath;

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('maketo')
            ->addArgument('obj', Argument::REQUIRED, "The name of the class name")
            ->addArgument('toapp', Argument::REQUIRED, "The name of the to app")
            ->addArgument('sysobj', Argument::OPTIONAL, "The name of the sys module")
            ->setDescription('创建应用下对象默认');
            //php think maketo user[对象名] toadmin[应用目录名]
            
    }

    protected function execute(Input $input, Output $output)
    {
        //路由route
        //验证器validate
        //控制器controller
        //调用命令
        //\think\facade\Console::call('make:model',['Hello'])->fetch();
        $this->basePath = $this->app->getBasePath();
        $name = trim($input->getArgument('obj'));
        $toapp = trim($input->getArgument('toapp'));
        $to = substr($toapp, 0,2);
        if($to != 'to'){
            $output->writeln("<info>set app [to] prefix! ". $toapp.'=>'.$to ."</info>");
            return ;
        }
        if(!$name){
            $output->writeln("<info>empty!</info>");
            return ;
        }
        $sysobj = trim($input->getArgument('sysobj')??'');
        $sysobj  = $sysobj?$sysobj:( 'sys'.substr($toapp,2) ); //sysobj为空取应用命名
        $sys = substr($sysobj, 0,3);
        if($sys != 'sys'){
            $output->writeln("<info>set service moudle [sys] prefix! ". $sysobj.'=>'.$sys ."</info>");
            return ;
        }

        $output->writeln("<info>  start to app arg... {$name} {$toapp} {$sysobj} </info>");
        //to应用创建
        $preNamespace = 'app' .'\\' . $toapp ; //app\touser
        $className = $this->getClassName($name);
        $this->buildController($toapp,$preNamespace,$className,$sysobj);
        $this->buildRoute($toapp,$preNamespace,$className);
        $this->buildValidate($toapp,$preNamespace,$className);

        //sys模块
        //model
        //dao
        //service

        $output->writeln("<info>Successed</info>");

    }
    
    //创建contoller
    protected function buildController(string $toapp, string $preNamespace,string $className,string $tosys): void
    {

        $suffix   = $this->app->config->get('route.controller_suffix') ? 'Controller' : '';
        $namespace = trim(implode('\\', array_slice(explode('\\', $className), 0, -1)), '\\');
        $class = str_replace($namespace . '\\', '', $className);

        $filename = $this->basePath . ($toapp ? $toapp . DIRECTORY_SEPARATOR : '') . 'controller' . DIRECTORY_SEPARATOR . ltrim(str_replace('\\', '/', $namespace), '/').($namespace?DIRECTORY_SEPARATOR:'').ucfirst($class). $suffix . '.php';
        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'tostubs' . DIRECTORY_SEPARATOR . 'controller.api.stub');
            $namespaceService = 'app' .'\\' . $tosys.'\\'.'service'.($namespace?'\\'.$namespace:'\\').ucfirst($class);
            $content = str_replace([
                '{%namespace%}',
                '{%className%}',
                '{%layer%}', 
                '{%service%}',
            ], [
                $preNamespace.'\\'.'controller'.($namespace?'\\'.$namespace:''), 
                ucfirst($class), 
                'controller', 
                $namespaceService
            ], $content);
            $this->checkDirBuild(dirname($filename));
            file_put_contents($filename, $content);
            $this->output->writeln($filename);
        }else{
            $this->output->writeln('file exist ...'.$filename);
        }
    }

    //路由
    protected function buildRoute(string $toapp, string $preNamespace,string $className): void
    {

        $suffix   = $this->app->config->get('route.controller_suffix') ? 'Controller' : '';
        $namespace = trim(implode('\\', array_slice(explode('\\', $className), 0, -1)), '\\');
        $class = str_replace($namespace . '\\', '', $className);

        $routePath =  ltrim(str_replace('\\', '_', $namespace).'_'.lcfirst($class), '_');
        $filename = $this->basePath . ($toapp ? $toapp . DIRECTORY_SEPARATOR : '') . 'route' . DIRECTORY_SEPARATOR .$routePath. $suffix . '.php';

        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'tostubs' . DIRECTORY_SEPARATOR . 'route.stub');

            $urlPath = str_replace('\\', '/', $namespace).'/'.$class;
            $urlPath = ltrim($urlPath,'/');

            $classRoute = str_replace('\\', '/', $namespace);
            $classRoute = str_replace('/', '.', $classRoute).'.'.ucfirst($class);
            $classRoute = ltrim($classRoute,'.');

            $content = str_replace(['{%obj%}', '{%class%}'], [$urlPath,$classRoute], $content);
            $this->checkDirBuild(dirname($filename));
            file_put_contents($filename, $content);
            $this->output->writeln($filename);
        }else{
            $this->output->writeln('file exist ...'.$filename);
        }
    }

    //验证器
    protected function buildValidate(string $toapp, string $preNamespace,string $className): void
    {

        $suffix   = $this->app->config->get('route.controller_suffix') ? 'Controller' : '';

        $namespace = trim(implode('\\', array_slice(explode('\\', $className), 0, -1)), '\\');
        $class = str_replace($namespace . '\\', '', $className);

        $filename = $this->basePath . ($toapp ? $toapp . DIRECTORY_SEPARATOR : '') . 'validate' . DIRECTORY_SEPARATOR . ltrim(str_replace('\\', '/', $namespace), '/').($namespace?DIRECTORY_SEPARATOR:'').ucfirst($class). $suffix . '.php';

        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'tostubs' . DIRECTORY_SEPARATOR . 'validate.stub');
            //$content = str_replace(['{%name%}', '{%app%}', '{%layer%}', '{%suffix%}'], [$app, $namespace, 'controller', $suffix], $content);
            //namespace className
           
            $content = str_replace(['{%namespace%}', '{%className%}', '{%layer%}', '{%suffix%}'], [$preNamespace.'\\'.'validate', ucfirst($class), 'validate', $suffix], $content);
            $this->checkDirBuild(dirname($filename));

            file_put_contents($filename, $content);
            $this->output->writeln($filename);
        }else{
            $this->output->writeln('file exist ...'.$filename);
        }
    }

    protected function getClassName(string $name): string
    {
        if (strpos($name, '\\') !== false) {
            return $name;
        }
        if (strpos($name, '/') !== false) {
            $name = str_replace('/', '\\', $name);
        }
        return $name;
    }

    /**
     * 创建目录
     * @access protected
     * @param  string $dirname 目录名称
     * @return void
     */
    protected function checkDirBuild(string $dirname): void
    {
        if (!is_dir($dirname)) {
            mkdir($dirname, 0755, true);
        }
    }

}
